﻿using Newtonsoft.Json;
using Onetube.Entities.SubscriptionQuery;
using Onetube.Providers.Interfaces;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Onetube.Providers
{
    public class YoutubeSubscriptionProvider : IYoutubeSubscriptionProvider
    {
        private YoutubeChannelProvider channelProvider;
      
        public async Task<IEnumerable<Models.Subscription.SubscriptionResult>> GetMySubscriptionsAsync(string token,string maxResults, CancellationTokenSource cancelTask)
        {
            StringBuilder petitionUri = new StringBuilder("https://www.googleapis.com/youtube/v3/subscriptions?");

            petitionUri.AppendFormat("part={0}", "snippet%2CcontentDetails");
            petitionUri.AppendFormat("&mine={0}", "true");
            petitionUri.AppendFormat("&order={0}", "alphabetical");
            petitionUri.AppendFormat("&maxResults={0}", 15);
            petitionUri.AppendFormat("&key={0}", AppKeys.API_KEY);
          
            var taskCompletitionSource = new TaskCompletionSource<SubscriptionQueryResult>();
            HttpWebRequest request = HttpWebRequest.CreateHttp(petitionUri.ToString());
            request.Headers["Authorization"] = "Bearer  " + token;
            var result = await ResolveRequest(request, taskCompletitionSource, cancelTask).ConfigureAwait(false);
            List<Models.Subscription.SubscriptionResult> list = new List<Models.Subscription.SubscriptionResult>();
            if (result != null)
            {
                if (result.Items.Any())
                {
                    if (channelProvider == null)
                    {
                        channelProvider = new YoutubeChannelProvider();
                    }
                    
                    foreach (var item in result.Items)
                    {
                        try
                        {
                            var data = new Models.Subscription.SubscriptionResult();
                            data.NextPageToken = result.NextPageToken;
                            data.SubcriptionId = item.Id;
                            Entities.ChannelsQuery.Item channel = null;
                            data.ChannelInfo = new Entities.ChannelsQuery.Item();
                            data.ChannelInfo.Id = item.Snippet.ResourceId.ChannelId;
                            data.ChannelInfo.Kind = item.Kind;
                            data.ChannelInfo.Snippet = new Entities.ChannelsQuery.Snippet();
                            data.ChannelInfo.Snippet.Description = string.Empty;
                            data.ChannelInfo.Snippet.Title = item.Snippet.Title;
                            data.ChannelInfo.Snippet.Thumbnails = new Entities.ChannelsQuery.Thumbnails();
                            data.ChannelInfo.Snippet.Thumbnails.Default = new Entities.ChannelsQuery.Default { Url = item.Snippet.Thumbnails.Default.Url };
                            data.ChannelInfo.Snippet.Thumbnails.High = new Entities.ChannelsQuery.High { Url = item.Snippet.Thumbnails.High.Url };
                            data.ChannelInfo.ContentDetails = new Entities.ChannelsQuery.ContentDetails();
                            data.ChannelInfo.ContentDetails.ActivityType = item.ContentDetails.ActivityType;
                            data.ChannelInfo.ContentDetails.NewItemCount = item.ContentDetails.NewItemCount;
                            list.Add(data);
                        }
                        catch (Exception ex)
                        {
                        }
                    }
                }
               
                
            }
            result = null;
            channelProvider = null;
            return list;
        }

        public async Task<IEnumerable<Models.Subscription.SubscriptionResult>> GetMySubscriptionsAsyncNextPage(string nextPage, string token,string maxResults, CancellationTokenSource cancelTask)
        {
            StringBuilder petitionUri = new StringBuilder("https://www.googleapis.com/youtube/v3/subscriptions?");

            petitionUri.AppendFormat("part={0}", "snippet%2CcontentDetails");
            petitionUri.AppendFormat("&mine={0}", "true");
            petitionUri.AppendFormat("&order={0}", "alphabetical");
            petitionUri.AppendFormat("&maxResults={0}", maxResults);
            petitionUri.AppendFormat("&pageToken={0}", nextPage);
            petitionUri.AppendFormat("&key={0}", AppKeys.API_KEY);
          
            var taskCompletitionSource = new TaskCompletionSource<SubscriptionQueryResult>();
            HttpWebRequest request = HttpWebRequest.CreateHttp(petitionUri.ToString());
            request.Headers["Authorization"] = "Bearer  " + token;
            var result = await ResolveRequest(request, taskCompletitionSource, cancelTask).ConfigureAwait(false);
            List<Models.Subscription.SubscriptionResult> list = new List<Models.Subscription.SubscriptionResult>();
        

            if (result != null)
            {
                if (result.Items.Any())
                {
                    if (channelProvider == null)
                    {
                        channelProvider = new YoutubeChannelProvider();
                    }
                    
                    foreach (var item in result.Items)
                    {
                        try
                        {
                            var data = new Models.Subscription.SubscriptionResult();
                            data.NextPageToken = result.NextPageToken;
                            data.SubcriptionId = item.Id;
                            Entities.ChannelsQuery.Item channel = null;
                            data.ChannelInfo = new Entities.ChannelsQuery.Item();
                            data.ChannelInfo.Id =  item.Snippet.ResourceId.ChannelId;
                            data.ChannelInfo.Kind = item.Kind;
                            data.ChannelInfo.Snippet = new Entities.ChannelsQuery.Snippet();
                            data.ChannelInfo.Snippet.Description = string.Empty;
                            data.ChannelInfo.Snippet.Title = item.Snippet.Title;
                            data.ChannelInfo.Snippet.Thumbnails = new Entities.ChannelsQuery.Thumbnails();
                            data.ChannelInfo.Snippet.Thumbnails.Default = new Entities.ChannelsQuery.Default { Url = item.Snippet.Thumbnails.Default.Url };
                            data.ChannelInfo.Snippet.Thumbnails.High = new Entities.ChannelsQuery.High { Url = item.Snippet.Thumbnails.High.Url };
                            data.ChannelInfo.ContentDetails = new Entities.ChannelsQuery.ContentDetails();
                            data.ChannelInfo.ContentDetails.ActivityType = item.ContentDetails.ActivityType;
                            data.ChannelInfo.ContentDetails.NewItemCount = item.ContentDetails.NewItemCount;
                            list.Add(data);
                        }
                        catch (Exception ex)
                        {
                        }
                    }
                }
               
                result = null;
            }

            return list;

           
        }

        private async Task<SubscriptionQueryResult> ResolveRequest(HttpWebRequest request, TaskCompletionSource<SubscriptionQueryResult> taskCompletitionSource, CancellationTokenSource cancelTask)
        {
            if (cancelTask == null)
            {
                cancelTask = new CancellationTokenSource();
            }
           
            using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("Authorization", request.Headers["Authorization"]);
                HttpResponseMessage response = await client.GetAsync(request.RequestUri.ToString(), cancelTask.Token).ConfigureAwait(false);
                
                string resultJson;
                using (StreamReader reader = new StreamReader(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), Encoding.UTF8))
                {
                    try
                    {
                        resultJson = await reader.ReadToEndAsync().ConfigureAwait(false);

                        if (!string.IsNullOrEmpty(resultJson))
                        {
                            var entries = JsonConvert.DeserializeObject<SubscriptionQueryResult>(resultJson);

                            taskCompletitionSource.SetResult(entries);
                            resultJson = null;
                            entries = null;
                        }
                        else
                        {
                            taskCompletitionSource.SetResult(null);
                        }
                        response.Dispose();
                        request.Abort();
                    }
                    catch (Exception ex)
                    {
                        taskCompletitionSource.SetException(ex);
                    }
                }
            }
            return await taskCompletitionSource.Task;
        }

        public async Task<bool> SubscribeToChannelAsync(string token, string channelToSubscribe, CancellationTokenSource cancelTask)
        {
            try
            {
                StringBuilder petitionUri = new StringBuilder("https://www.googleapis.com/youtube/v3/subscriptions?");
                petitionUri.AppendFormat("part={0}", "snippet");
                petitionUri.AppendFormat("&key={0}", AppKeys.API_KEY);
                Entities.EntitiesRequest.SnippetSubscription t1 = new Entities.EntitiesRequest.SnippetSubscription();
                t1.snippet = new Entities.EntitiesRequest.SnippetSubscription.Snippet();
                t1.snippet.resourceId = new Entities.EntitiesRequest.SnippetSubscription.ResourceId { channelId = channelToSubscribe };
                DataContractJsonSerializer jsondata = new DataContractJsonSerializer(typeof(Entities.EntitiesRequest.SnippetSubscription));
                MemoryStream mem = new MemoryStream();
                jsondata.WriteObject(mem, t1);
                string josnserdata = Encoding.UTF8.GetString(mem.ToArray(), 0, (int)mem.Length);
                var request = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Post,petitionUri.ToString());
              
                request.Content = new StreamContent(new MemoryStream(Encoding.UTF8.GetBytes(josnserdata.ToString())));
                HttpClient client = new HttpClient();
                client.DefaultRequestHeaders.Add("Authorization", "Bearer  " + token);
                request.Content.Headers.Add("Content-Type", "application/json");
                
                System.Net.Http.HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false);
                var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                responseContent = null;
                jsondata = null;
                josnserdata = null;
                request.Dispose();
                client.Dispose();
                response.Dispose(); mem.Dispose();
                return true;
            }
            catch (Exception)
            {
            }

            return false;
          
        }

        public async Task<bool> IsUserSubscribed(string token, string channelToSubscribe, CancellationTokenSource cancelTask)
        {
            StringBuilder petitionUri = new StringBuilder("https://www.googleapis.com/youtube/v3/subscriptions?");

            petitionUri.AppendFormat("part={0}", "snippet");
            petitionUri.AppendFormat("&mine={0}", "true");
            petitionUri.AppendFormat("&forChannelId={0}", channelToSubscribe);
            petitionUri.AppendFormat("&key={0}", AppKeys.API_KEY);
          
            var taskCompletitionSource = new TaskCompletionSource<SubscriptionQueryResult>();
            HttpWebRequest request = HttpWebRequest.CreateHttp(petitionUri.ToString());
            request.Headers["Authorization"] = "Bearer  " + token;
            var result = await ResolveRequest(request, taskCompletitionSource, cancelTask).ConfigureAwait(false);
            if (result != null)
            {
                if (result.Items != null)
                {
                    if (result.Items.Any())
                    {
                        result = null;
                        
                        return true;
                    }
                }
            }
            return false;
        }

        public async Task<bool> UnsubcribeToChannelAsync(string token, string channelToUnsibcribe, CancellationTokenSource cancelTask)
        {
            StringBuilder petitionUri = new StringBuilder("https://www.googleapis.com/youtube/v3/subscriptions?");

            petitionUri.AppendFormat("part={0}", "snippet");
            petitionUri.AppendFormat("&mine={0}", "true");
            petitionUri.AppendFormat("&forChannelId={0}", channelToUnsibcribe);
            petitionUri.AppendFormat("&key={0}", AppKeys.API_KEY);
          
            var taskCompletitionSource = new TaskCompletionSource<SubscriptionQueryResult>();
            HttpWebRequest request = HttpWebRequest.CreateHttp(petitionUri.ToString());
            request.Headers["Authorization"] = "Bearer  " + token;
            var result = await ResolveRequest(request, taskCompletitionSource, cancelTask).ConfigureAwait(false);
            if (result != null)
            {
                if (result.Items != null)
                {
                    if (result.Items.Any())
                    {
                        try
                        {
                            var subscriber = result.Items.Where(x => x.Snippet.ResourceId.ChannelId.Equals(channelToUnsibcribe)).FirstOrDefault();
                            if (subscriber != null)
                            {
                                petitionUri = new StringBuilder("https://www.googleapis.com/youtube/v3/subscriptions?");

                                petitionUri.AppendFormat("id={0}", subscriber.Id);
                            
                                petitionUri.AppendFormat("&key={0}", AppKeys.API_KEY);
          
                                taskCompletitionSource = new TaskCompletionSource<SubscriptionQueryResult>();
                                request = HttpWebRequest.CreateHttp(petitionUri.ToString());
                                request.Method = "DELETE";
                                request.Headers["Authorization"] = "Bearer  " + token;
                                var response = await request.GetResponseAsync().ConfigureAwait(false);
                                var r = response.GetResponseStream();
                                response.Dispose();
                                r.Dispose();
                                result = null;
                                //var confirmDelete = await ResolveRequest(request, taskCompletitionSource, cancelTask);
                            }
                            return true;
                        }
                        catch (Exception)
                        {
                            return false;
                        }
                    }
                }
            }
            return false;
        }
    }
}